# -*- coding:utf-8 -*-
import os
import sys
import pandas as pd
import numpy as np
from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                            QPushButton, QLabel, QFileDialog, QMessageBox,
                            QTableWidget, QTableWidgetItem, QHeaderView, QSplitter,
                            QSizePolicy)
from PyQt5.QtCore import Qt, QPointF
from PyQt5.QtGui import QPainter, QPen, QColor
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from config import AppConfig
from data_processor import ProcessData

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

class MplCanvas(FigureCanvas):
    """Matplotlib画布"""
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self.fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = self.fig.add_subplot(111)
        super().__init__(self.fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self, 
                                   QSizePolicy.Expanding, 
                                   QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)

class CompareUI(QMainWindow):
    """测量点与检查线比较界面"""
    def __init__(self):
        super().__init__()
        self.config = AppConfig()
        self.processor = ProcessData(self.config)
        self.data_a = None  # 存储测量点数据
        self.data_b = None  # 存储检查线数据
        self.coincident_points = None  # 存储重合点数据
        self.init_ui()
    
    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle('测量点与检查线比较工具')
        self.resize(1000, 800)
        
        # 中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 按钮区域布局
        button_layout = QHBoxLayout()
        
        # 导入按钮
        self.import_a_btn = QPushButton('导入测量点A')
        self.import_a_btn.clicked.connect(self.import_data_a)
        self.import_b_btn = QPushButton('导入检查线B')
        self.import_b_btn.clicked.connect(self.import_data_b)
        self.compare_btn = QPushButton('计算重合点高程较差')
        self.compare_btn.clicked.connect(self.calculate_coincident_points)
        self.compare_btn.setEnabled(False)
        
        # 距离阈值输入
        self.threshold_label = QLabel('距离阈值(米):')
        self.threshold_input = QLabel('1.0')
        
        # 添加到按钮布局
        button_layout.addWidget(self.import_a_btn)
        button_layout.addWidget(self.import_b_btn)
        button_layout.addWidget(self.threshold_label)
        button_layout.addWidget(self.threshold_input)
        button_layout.addWidget(self.compare_btn)
        button_layout.addStretch()
        
        # 状态栏
        self.status_label = QLabel('等待导入数据...')
        
        # 创建分割器
        splitter = QSplitter(Qt.Vertical)
        
        # 创建表格显示区域
        self.table_widget = QTableWidget()
        self.table_widget.setColumnCount(6)
        self.table_widget.setHorizontalHeaderLabels(['X坐标', 'Y坐标', 'A点高程', 'B点高程', '高程较差', '距离'])
        self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        
        # 创建图形显示区域
        self.canvas_widget = MplCanvas(self, width=5, height=4, dpi=100)
        
        # 添加到分割器
        splitter.addWidget(self.table_widget)
        splitter.addWidget(self.canvas_widget)
        
        # 设置初始大小比例
        splitter.setSizes([300, 500])
        
        # 添加到主布局
        main_layout.addLayout(button_layout)
        main_layout.addWidget(self.status_label)
        main_layout.addWidget(splitter)
    
    def import_data_a(self):
        try:
            from PyQt5.QtWidgets import QFileDialog, QMessageBox
            import os
            
            # 选择文件
            file_in, _ = QFileDialog.getOpenFileName(
                self, 
                "选择数据文件", 
                "", 
                "LOG文件 (*.LOG)"
            )
            
            if not file_in:
                return
            
            print(f"开始导入文件: {file_in}")
            
            # 初始化数据
            filepath, tempfilename = os.path.split(file_in)
            filepath = filepath.replace('/', '\\')
            
            self.controller.config.notesection = []
            self.controller.config.notemenu = []
            try:
                # 读取文件
                with open(file_in, 'r') as f:
                    for line in f:
                        line = line.strip('\n')
                        
                        # 定位文件名中的位置信息，作为日志文件名的一部分
                        e = line.rfind('\\')
                        fi = line[e+1:] if e != -1 else line
                        
                        # 与原代码完全一致的路径拼接方式
                        full_path = filepath + '\\' + fi
                        
                        # 检查文件是否存在
                        if not os.path.exists(full_path):
                            print(f"文件不存在: {full_path}")
                            continue
                            
                        self.controller.config.notesection.append(fi)
                        self.controller.config.notemenu.append(full_path)
            except Exception as e:
                print(f"处理文件 {filepath} 时发生错误: {e}")
            
            # 添加调试信息
            print(f"找到 {len(self.controller.config.notesection)} 个断面")
            
        
            # 批量处理每个断面前，确保列表长度足够
            total_sections = len(self.controller.config.notesection)
            
            for i in range(total_sections):
                self.config.ytfx.append(0)
                self.controller.config.dmnum = i
                try:
                    # 1. 初始化
                    self.processor._init_data_structures()
                    print(f"初始化断面{i}数据结构")
                    # 2. 使用_read_and_parse_file函数读取和解析文件
                    self.processor._read_and_parse_file()
                    print(f"成功读取并解析断面{i}数据")
                    # 3. 使用_merge_ec1_and_pos_data函数合并EC1和POS数据
                    self.processor._merge_ec1_and_pos_data()
                    print(f"成功合并断面{i}的EC1和POS数据")
                except:
                    pass
                    
                # 更新进度
                progress.setValue(int((i + 1) / total_sections * 100))
                QApplication.processEvents()  # 刷新UI
            
            # 关闭进度对话框
            progress.close()
        except:
            pass
    
    def import_data_b(self):
        """导入检查线B数据"""
        file_path, _ = QFileDialog.getOpenFileName(self, "选择检查线文件", "", "文本文件 (*.txt);;CSV文件 (*.csv);;所有文件 (*.*)")
        if file_path:
            try:
                # 尝试读取文件（假设为空格分隔的文本文件，格式为x y z）
                self.data_b = self._read_point_file(file_path)
                self.status_label.setText(f"已导入检查线B数据，共{len(self.data_b)}个点")
                QMessageBox.information(self, "成功", f"检查线B导入成功，共{len(self.data_b)}个点")
                self._check_enable_compare()
            except Exception as e:
                QMessageBox.critical(self, "错误", f"导入检查线B失败：{str(e)}")
    
    def _read_point_file(self, file_path):
        """读取点文件"""
        # 根据文件扩展名尝试不同的读取方式
        ext = os.path.splitext(file_path)[1].lower()
        
        if ext == '.csv':
            # 尝试CSV格式
            try:
                df = pd.read_csv(file_path)
                # 假设CSV有列名，尝试找到X,Y,Z列
                for col in df.columns:
                    if 'x' in col.lower():
                        x_col = col
                    if 'y' in col.lower():
                        y_col = col
                    if 'z' in col.lower() or 'h' in col.lower() or '高程' in col.lower():
                        z_col = col
                return df[[x_col, y_col, z_col]].values
            except:
                # 如果CSV读取失败，尝试文本格式
                pass
        
        # 尝试文本格式（空格或制表符分隔）
        try:
            # 尝试自动检测分隔符
            with open(file_path, 'r') as f:
                first_line = f.readline()
                if '\t' in first_line:
                    delimiter = '\t'
                else:
                    delimiter = None  # 让pandas自动检测
            
            # 尝试跳过可能的表头
            df = pd.read_csv(file_path, sep=delimiter, header=None, skiprows=0)
            # 假设前3列是x,y,z
            return df.iloc[:, :3].values
        except:
            # 最后尝试使用numpy读取
            return np.loadtxt(file_path)[:,:3]
    
    def _check_enable_compare(self):
        """检查是否可以启用比较按钮"""
        if self.data_a is not None and self.data_b is not None:
            self.compare_btn.setEnabled(True)
            self.status_label.setText(f"已导入测量点A({len(self.data_a)}点)和检查线B({len(self.data_b)}点)，可以开始比较")
    
    def calculate_coincident_points(self):
        """计算重合点和高程较差"""
        if self.data_a is None or self.data_b is None:
            QMessageBox.warning(self, "警告", "请先导入测量点A和检查线B的数据")
            return
        
        try:
            # 设置距离阈值（可根据需要调整）
            threshold = 1.0  # 1米
            
            # 存储重合点信息
            coincident_list = []
            
            # 计算重合点
            for a_point in self.data_a:
                a_x, a_y, a_z = a_point
                
                # 找到B中距离最近的点
                min_dist = float('inf')
                closest_point = None
                
                for b_point in self.data_b:
                    b_x, b_y, b_z = b_point
                    # 计算欧氏距离
                    dist = np.sqrt((a_x - b_x)**2 + (a_y - b_y)** 2)
                    
                    if dist < min_dist:
                        min_dist = dist
                        closest_point = b_point
                
                # 如果最近点距离小于阈值，则认为是重合点
                if min_dist <= threshold and closest_point is not None:
                    b_x, b_y, b_z = closest_point
                    elevation_diff = a_z - b_z  # 高程较差
                    coincident_list.append([a_x, a_y, a_z, b_z, elevation_diff, min_dist])
            
            # 转换为numpy数组
            self.coincident_points = np.array(coincident_list)
            
            # 显示结果
            self._display_results()
            self._plot_results()
            
            # 更新状态栏
            self.status_label.setText(f"找到{len(self.coincident_points)}个重合点")
            QMessageBox.information(self, "成功", f"计算完成，找到{len(self.coincident_points)}个重合点")
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"计算重合点失败：{str(e)}")
    
    def _display_results(self):
        """在表格中显示结果"""
        if self.coincident_points is None or len(self.coincident_points) == 0:
            self.table_widget.setRowCount(0)
            return
        
        # 设置表格行数
        self.table_widget.setRowCount(len(self.coincident_points))
        
        # 填充表格数据
        for i, point in enumerate(self.coincident_points):
            x, y, a_z, b_z, diff, dist = point
            
            # 设置表格项
            self.table_widget.setItem(i, 0, QTableWidgetItem(f"{x:.3f}"))
            self.table_widget.setItem(i, 1, QTableWidgetItem(f"{y:.3f}"))
            self.table_widget.setItem(i, 2, QTableWidgetItem(f"{a_z:.3f}"))
            self.table_widget.setItem(i, 3, QTableWidgetItem(f"{b_z:.3f}"))
            self.table_widget.setItem(i, 4, QTableWidgetItem(f"{diff:.3f}"))
            self.table_widget.setItem(i, 5, QTableWidgetItem(f"{dist:.3f}"))
            
            # 设置高程较差单元格的颜色
            item = self.table_widget.item(i, 4)
            # 根据差值大小设置不同的颜色
            if abs(diff) > 0.5:
                item.setBackground(QColor(255, 200, 200))  # 差值较大时显示红色
            elif abs(diff) > 0.2:
                item.setBackground(QColor(255, 255, 200))  # 差值中等时显示黄色
            else:
                item.setBackground(QColor(200, 255, 200))  # 差值较小时显示绿色
    
    def _plot_results(self):
        """绘制结果图形"""
        self.canvas_widget.axes.clear()
        
        # 绘制所有点
        if self.data_a is not None:
            self.canvas_widget.axes.scatter(self.data_a[:, 0], self.data_a[:, 1], c='blue', s=10, label='测量点A')
        
        if self.data_b is not None:
            self.canvas_widget.axes.scatter(self.data_b[:, 0], self.data_b[:, 1], c='green', s=10, label='检查线B')
        
        # 绘制重合点
        if self.coincident_points is not None and len(self.coincident_points) > 0:
            self.canvas_widget.axes.scatter(self.coincident_points[:, 0], self.coincident_points[:, 1], 
                                           c='red', s=30, marker='*', label='重合点')
        
        # 添加标签和图例
        self.canvas_widget.axes.set_xlabel('X坐标')
        self.canvas_widget.axes.set_ylabel('Y坐标')
        self.canvas_widget.axes.set_title('测量点与检查线重合点分布图')
        self.canvas_widget.axes.legend()
        self.canvas_widget.axes.grid(True)
        
        # 调整坐标轴比例
        self.canvas_widget.axes.set_aspect('equal')
        
        # 刷新图形
        self.canvas_widget.draw()

# 如果作为主程序运行
if __name__ == '__main__':
    from PyQt5.QtWidgets import QApplication
    app = QApplication(sys.argv)
    window = CompareUI()
    window.show()
    sys.exit(app.exec_())